package com.leigq.dynamic.task.task;

import com.leigq.basaltools.util.UUIDUtils;
import com.leigq.dynamic.task.util.RedisLock;
import com.leigq.dynamic.task.web.BaseDynamicTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

/**
 * 可修改执行周期的动态任务
 * <br/>
 * <ul>
 * <li>
 * <a href='http://note.youdao.com/noteshare?id=09c1497aa12dbd944ee9c5cc103eb07c'>Spring学习——Spring中定时器实现</a>
 * </li>
 * <li>
 * <a href='http://cron.qqe2.com/'>在线Cron表达式生成器</a>
 * </li>
 * </ul>
 *
 * @author leiguoqing
 */
@Slf4j
@Component
public class DynamicTask extends BaseDynamicTask {


    private final RedisLock redisLock;

    /**
     * The constant TYPE.
     */
    public static final String TYPE = "testDynamicTask";


    private static final String LOCK_KEY = "DynamicTaskLock";


    public DynamicTask(RedisLock redisLock) {
        this.redisLock = redisLock;
    }


    // 任务触发，可修改任务的执行周期
    // 在线Cron表达式生成器：http://cron.qqe2.com
    // 每十秒钟执行一次*/10 * * * * ?
    // 每十分钟执行一次0 */10 * * * ?
    // 每半小时执行一次0 */30 * * * ?
    // 每一个小时执行一次0 0 * * * ?
    // 每两个小时执行一次0 0 0/2 * * ?
    // 每天凌晨3点0 0 3 */1 * ?
    // 每天凌晨12点0 0 0 */1 * ?

    /**
     * Test.
     */
    private void test() {
        // 添加分布式锁，防止多实例重复执行
        log.warn("执行一些任务......");
    }

    /**
     * Type string.
     *
     * @return the string
     */
    @Override
    public String type() {
        return TYPE;
    }

    /**
     * Gets task.
     *
     * @return the task
     */
    @Override
    public Runnable getTask() {
        return () -> {
            String requestId = UUIDUtils.genUnsignedId();
            // 添加分布式锁，防止多个实例执行多次任务
            final boolean lock = redisLock.lock(LOCK_KEY, requestId, 20);

            if (lock) {
                log.info("获取锁成功...");
                try {
                    test();
                    // 线程休眠1秒中，打印执行太快，防止多个实例看似同时获取到分布式锁
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    redisLock.unLock(LOCK_KEY, requestId);
                }
            }
        };
    }

    /**
     * Gets trigger.
     *
     * @return the trigger
     */
    @Override
    public CronTrigger getTrigger() {
        // 可以从数据库获取 cron 表达式
        String cron = "*/10 * * * * ?";
        return new CronTrigger(cron);
    }

    /**
     * Sets trigger.
     *
     * @param cron the cron
     * @return the trigger
     */
    @Override
    public CronTrigger setTrigger(String cron) {
        return new CronTrigger(cron);
    }
}
